package com.snailframework.gateway.filter;

import com.snailframework.start.utils.id.ObjectId;
import com.snailframework.start.utils.threadlocal.UserContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @author: zgadmin(zhangge)
 * @Date: 2023/2/20 下午2:54
 * @Version: 1.0.0
 */
@Slf4j
@Component
public class TracingFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        MDC.clear();
        UserContextUtils.clear();
        ServerHttpRequest request = exchange.getRequest();
        //国际化
        String locale = request.getHeaders().getFirst("locale");
        if (null != locale && !"".equals(locale)) {
            UserContextUtils.setOnlyLocale(locale);
        }
        //trace
        String trace = request.getHeaders().getFirst("ETR-TRACE");
        if (null == trace || "".equalsIgnoreCase(trace)) {
            trace = ObjectId.nextId();
            request.mutate().header("ETR-TRACE-ID", trace);
        }
        String span = ObjectId.nextId();
        request.mutate().header("ETR-SPAN-ID", span);
        request.mutate().header("ETR-PARENT-ID", span);
        MDC.put("traceId", trace);
        MDC.put("parentId", span);
        MDC.put("spanId", span);
        UserContextUtils.setOnlyTracing(span, span, trace);
        log.info("-----------------------Tracing Start---------------------------------");
        log.info("tracing path:{},method:{},headers:{}", exchange.getRequest().getURI().getPath(), method(exchange), headers(exchange));
        log.info("-----------------------Tracing End-----------------------------------");
        return chain.filter(exchange);
    }

    String headers(ServerWebExchange exchange) {
        return exchange.getRequest().getHeaders().toString();
    }

    String method(ServerWebExchange exchange) {
        HttpMethod method = exchange.getRequest().getMethod();
        if (null == method) {
            return "*";
        }
        return method.name();
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}
